; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -opaque-pointers=0 -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
; RUN: opt -opaque-pointers=0 -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC

; NOT_CGSCC___: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
; IS__CGSCC___: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)]
@dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)]

declare void @no_return_call() nofree noreturn nounwind nosync

declare void @normal_call() readnone

declare i32 @foo()

declare i32 @foo_nounwind() nounwind

declare i32 @foo_noreturn_nounwind() noreturn nounwind

declare i32 @foo_noreturn() noreturn

declare i32 @bar() nosync readnone

; This internal function has no live call sites, so all its BBs are considered dead,
; and nothing should be deduced for it.

;.
; TUNIT: @[[DEAD_WITH_BLOCKADDRESS_USERS_L:[a-zA-Z0-9_$"\\.-]+]] = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)]
; TUNIT: @[[A1:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 8
; TUNIT: @[[A2:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 16
; TUNIT: @[[E:[a-zA-Z0-9_$"\\.-]+]] = global %struct.a* null
; TUNIT: @[[P:[a-zA-Z0-9_$"\\.-]+]] = global i8 0
;.
; CGSCC: @[[DEAD_WITH_BLOCKADDRESS_USERS_L:[a-zA-Z0-9_$"\\.-]+]] = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, [[LAB0:%.*]]), i8* blockaddress(@dead_with_blockaddress_users, [[END:%.*]])]
; CGSCC: @[[A1:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 8
; CGSCC: @[[A2:[a-zA-Z0-9_$"\\.-]+]] = common global i8 0, align 16
; CGSCC: @[[E:[a-zA-Z0-9_$"\\.-]+]] = global %struct.a* null
; CGSCC: @[[P:[a-zA-Z0-9_$"\\.-]+]] = global i8 0
;.
define internal i32 @dead_internal_func(i32 %0) {
; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@dead_internal_func
; CGSCC-SAME: () #[[ATTR6:[0-9]+]] {
; CGSCC-NEXT:    br label [[TMP2:%.*]]
; CGSCC:       1:
; CGSCC-NEXT:    ret i32 undef
; CGSCC:       2:
; CGSCC-NEXT:    [[TMP3:%.*]] = phi i32 [ [[TMP6:%.*]], [[TMP2]] ], [ 1, [[TMP0:%.*]] ]
; CGSCC-NEXT:    [[TMP4:%.*]] = phi i32 [ [[TMP5:%.*]], [[TMP2]] ], [ 1, [[TMP0]] ]
; CGSCC-NEXT:    [[TMP5]] = mul nsw i32 [[TMP3]], [[TMP4]]
; CGSCC-NEXT:    [[TMP6]] = add nuw nsw i32 [[TMP3]], 1
; CGSCC-NEXT:    [[TMP7:%.*]] = icmp eq i32 [[TMP3]], 10
; CGSCC-NEXT:    br i1 [[TMP7]], label [[TMP1:%.*]], label [[TMP2]]
;
  %2 = icmp slt i32 %0, 1
  br i1 %2, label %3, label %5

; <label>:3:                                      ; preds = %5, %1
  %4 = phi i32 [ 1, %1 ], [ %8, %5 ]
  ret i32 %4

; <label>:5:                                      ; preds = %1, %5
  %6 = phi i32 [ %9, %5 ], [ 1, %1 ]
  %7 = phi i32 [ %8, %5 ], [ 1, %1 ]
  %8 = mul nsw i32 %6, %7
  %9 = add nuw nsw i32 %6, 1
  %10 = icmp eq i32 %6, %0
  br i1 %10, label %3, label %5
}

define i32 @volatile_load(i32*) norecurse nounwind uwtable {
; TUNIT: Function Attrs: nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
; TUNIT-LABEL: define {{[^@]+}}@volatile_load
; TUNIT-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR6:[0-9]+]] {
; TUNIT-NEXT:    [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4
; TUNIT-NEXT:    ret i32 [[TMP2]]
;
; CGSCC: Function Attrs: nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable
; CGSCC-LABEL: define {{[^@]+}}@volatile_load
; CGSCC-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
; CGSCC-NEXT:    [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4
; CGSCC-NEXT:    ret i32 [[TMP2]]
;
  %2 = load volatile i32, i32* %0, align 4
  ret i32 %2
}

define internal i32 @internal_load(i32*) norecurse nounwind uwtable {
; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) uwtable
; CGSCC-LABEL: define {{[^@]+}}@internal_load
; CGSCC-SAME: () #[[ATTR8:[0-9]+]] {
; CGSCC-NEXT:    ret i32 undef
;
  %2 = load i32, i32* %0, align 4
  ret i32 %2
}
; TEST 1: Only first block is live.

define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 {
; CHECK: Function Attrs: nofree noreturn nosync nounwind
; CHECK-LABEL: define {{[^@]+}}@first_block_no_return
; CHECK-SAME: (i32 [[A:%.*]], i32* nocapture nofree nonnull readnone [[PTR1:%.*]], i32* nocapture nofree readnone [[PTR2:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    call void @no_return_call() #[[ATTR3:[0-9]+]]
; CHECK-NEXT:    unreachable
; CHECK:       cond.true:
; CHECK-NEXT:    unreachable
; CHECK:       cond.false:
; CHECK-NEXT:    unreachable
; CHECK:       cond.end:
; CHECK-NEXT:    unreachable
;
entry:
  call i32 @internal_load(i32* %ptr1)
  call void @no_return_call()
  call i32 @dead_internal_func(i32 10)
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call i32 @internal_load(i32* %ptr2)
  %load = call i32 @volatile_load(i32* %ptr1)
  call void @normal_call()
  %call = call i32 @foo()
  br label %cond.end

cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %cond.true
  %cond = phi i32 [ %call, %cond.true ], [ %call1, %cond.false ]
  ret i32 %cond
}

; TEST 2: cond.true is dead, but cond.end is not, since cond.false is live

; This is just an example. For example we can put a sync call in a
; dead block and check if it is deduced.

define i32 @dead_block_present(i32 %a, i32* %ptr1) #0 {
; CHECK-LABEL: define {{[^@]+}}@dead_block_present
; CHECK-SAME: (i32 [[A:%.*]], i32* nofree [[PTR1:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @no_return_call() #[[ATTR3]]
; CHECK-NEXT:    unreachable
; CHECK:       cond.false:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.end:
; CHECK-NEXT:    ret i32 [[CALL1]]
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @no_return_call()
  %call = call i32 @volatile_load(i32* %ptr1)
  br label %cond.end

cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %cond.true
  %cond = phi i32 [ %call, %cond.true ], [ %call1, %cond.false ]
  ret i32 %cond
}

; TEST 3: both cond.true and cond.false are dead, therfore cond.end is dead as well.

define i32 @all_dead(i32 %a) #0 {
; CHECK: Function Attrs: noreturn
; CHECK-LABEL: define {{[^@]+}}@all_dead
; CHECK-SAME: (i32 [[A:%.*]]) #[[ATTR4:[0-9]+]] {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @no_return_call() #[[ATTR3]]
; CHECK-NEXT:    unreachable
; CHECK:       cond.false:
; CHECK-NEXT:    call void @no_return_call() #[[ATTR3]]
; CHECK-NEXT:    unreachable
; CHECK:       cond.end:
; CHECK-NEXT:    unreachable
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @no_return_call()
  call i32 @dead_internal_func(i32 10)
  %call = call i32 @foo()
  br label %cond.end

cond.false:                                       ; preds = %entry
  call void @no_return_call()
  call i32 @dead_internal_func(i32 10)
  %call1 = call i32 @bar()
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %cond.true
  %cond = phi i32 [ %call, %cond.true ], [ %call1, %cond.false ]
  ret i32 %cond
}

declare i32 @__gxx_personality_v0(...)

; TEST 4: All blocks are live.

define i32 @all_live(i32 %a) #0 {
; CHECK-LABEL: define {{[^@]+}}@all_live
; CHECK-SAME: (i32 [[A:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL:%.*]] = call i32 @foo_noreturn() #[[ATTR4]]
; CHECK-NEXT:    unreachable
; CHECK:       cond.false:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.end:
; CHECK-NEXT:    ret i32 [[CALL1]]
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @normal_call()
  %call = call i32 @foo_noreturn()
  br label %cond.end

cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %cond.true
  %cond = phi i32 [ %call, %cond.true ], [ %call1, %cond.false ]
  ret i32 %cond
}

; TEST 5.1 noreturn invoke instruction with a unreachable normal successor block.

define i32 @invoke_noreturn(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: define {{[^@]+}}@invoke_noreturn
; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL:%.*]] = invoke i32 @foo_noreturn() #[[ATTR4]]
; CHECK-NEXT:    to label [[CONTINUE:%.*]] unwind label [[CLEANUP:%.*]]
; CHECK:       cond.false:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.end:
; CHECK-NEXT:    ret i32 [[CALL1]]
; CHECK:       continue:
; CHECK-NEXT:    unreachable
; CHECK:       cleanup:
; CHECK-NEXT:    [[RES:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT:    catch i8* null
; CHECK-NEXT:    ret i32 0
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @normal_call()
  %call = invoke i32 @foo_noreturn() to label %continue
  unwind label %cleanup

cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %continue
  %cond = phi i32 [ %call, %continue ], [ %call1, %cond.false ]
  ret i32 %cond

continue:
  br label %cond.end

cleanup:
  %res = landingpad { i8*, i32 }
  catch i8* null
  ret i32 0
}

; TEST 5.2 noreturn invoke instruction replaced by a call and an unreachable instruction
; put after it.

define i32 @invoke_noreturn_nounwind(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: define {{[^@]+}}@invoke_noreturn_nounwind
; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL:%.*]] = call i32 @foo_noreturn_nounwind() #[[ATTR3]]
; CHECK-NEXT:    unreachable
; CHECK:       cond.false:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.end:
; CHECK-NEXT:    ret i32 [[CALL1]]
; CHECK:       continue:
; CHECK-NEXT:    unreachable
; CHECK:       cleanup:
; CHECK-NEXT:    unreachable
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @normal_call()
  %call = invoke i32 @foo_noreturn_nounwind() to label %continue
  unwind label %cleanup


cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %continue
  %cond = phi i32 [ %call, %continue ], [ %call1, %cond.false ]
  ret i32 %cond

continue:
  br label %cond.end

cleanup:
  %res = landingpad { i8*, i32 }
  catch i8* null
  ret i32 0
}

; TEST 5.3 unounwind invoke instruction replaced by a call and a branch instruction put after it.
define i32 @invoke_nounwind(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind
; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL:%.*]] = call i32 @foo_nounwind() #[[ATTR2:[0-9]+]]
; CHECK-NEXT:    br label [[CONTINUE:%.*]]
; CHECK:       cond.false:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.end:
; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[CALL]], [[CONTINUE]] ], [ [[CALL1]], [[COND_FALSE]] ]
; CHECK-NEXT:    ret i32 [[COND]]
; CHECK:       continue:
; CHECK-NEXT:    br label [[COND_END]]
; CHECK:       cleanup:
; CHECK-NEXT:    unreachable
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @normal_call()
  %call = invoke i32 @foo_nounwind() to label %continue
  unwind label %cleanup

cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %cond.end

cond.end:                                         ; preds = %cond.false, %continue
  %cond = phi i32 [ %call, %continue ], [ %call1, %cond.false ]
  ret i32 %cond

continue:
  br label %cond.end

cleanup:
  %res = landingpad { i8*, i32 }
  catch i8* null
  ret i32 0
}

; TEST 5.4 unounwind invoke instruction replaced by a call and a branch instruction put after it.
define i32 @invoke_nounwind_phi(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind_phi
; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL:%.*]] = call i32 @foo_nounwind() #[[ATTR2]]
; CHECK-NEXT:    br label [[CONTINUE:%.*]]
; CHECK:       cond.false:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar()
; CHECK-NEXT:    br label [[CONTINUE]]
; CHECK:       continue:
; CHECK-NEXT:    [[P:%.*]] = phi i32 [ 0, [[COND_TRUE]] ], [ 1, [[COND_FALSE]] ]
; CHECK-NEXT:    ret i32 [[P]]
; CHECK:       cleanup:
; CHECK-NEXT:    unreachable
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @normal_call()
  %call = invoke i32 @foo_nounwind() to label %continue
  unwind label %cleanup

cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %continue

continue:
  %p = phi i32 [ 0, %cond.true ], [ 1, %cond.false ]
  ret i32 %p

cleanup:
  %res = landingpad { i8*, i32 } catch i8* null
  ret i32 0
}

; TEST 5.5 unounwind invoke instruction replaced by a call and a branch instruction put after it.
define i32 @invoke_nounwind_phi_dom(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind_phi_dom
; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[A]], 0
; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
; CHECK:       cond.true:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL:%.*]] = call i32 @foo_nounwind() #[[ATTR2]]
; CHECK-NEXT:    br label [[CONTINUE:%.*]]
; CHECK:       cond.false:
; CHECK-NEXT:    call void @normal_call()
; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar()
; CHECK-NEXT:    br label [[CONTINUE]]
; CHECK:       continue:
; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[CALL]], [[COND_TRUE]] ], [ [[CALL1]], [[COND_FALSE]] ]
; CHECK-NEXT:    ret i32 [[P]]
; CHECK:       cleanup:
; CHECK-NEXT:    unreachable
;
entry:
  %cmp = icmp eq i32 %a, 0
  br i1 %cmp, label %cond.true, label %cond.false

cond.true:                                        ; preds = %entry
  call void @normal_call()
  %call = invoke i32 @foo_nounwind() to label %continue
  unwind label %cleanup

cond.false:                                       ; preds = %entry
  call void @normal_call()
  %call1 = call i32 @bar()
  br label %continue

continue:
  %p = phi i32 [ %call, %cond.true ], [ %call1, %cond.false ]
  ret i32 %p

cleanup:
  %res = landingpad { i8*, i32 } catch i8* null
  ret i32 0
}

; TEST 6: Undefined behvior, taken from LangRef.
; FIXME: Should be able to detect undefined behavior.

define void @ub(i32* %0) {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(argmem: write)
; TUNIT-LABEL: define {{[^@]+}}@ub
; TUNIT-SAME: (i32* nocapture nofree writeonly [[TMP0:%.*]]) #[[ATTR7:[0-9]+]] {
; TUNIT-NEXT:    [[POISON:%.*]] = sub nuw i32 0, 1
; TUNIT-NEXT:    [[STILL_POISON:%.*]] = and i32 [[POISON]], 0
; TUNIT-NEXT:    [[POISON_YET_AGAIN:%.*]] = getelementptr i32, i32* [[TMP0]], i32 [[STILL_POISON]]
; TUNIT-NEXT:    store i32 0, i32* [[POISON_YET_AGAIN]], align 4
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CGSCC-LABEL: define {{[^@]+}}@ub
; CGSCC-SAME: (i32* nocapture nofree writeonly [[TMP0:%.*]]) #[[ATTR9:[0-9]+]] {
; CGSCC-NEXT:    [[POISON:%.*]] = sub nuw i32 0, 1
; CGSCC-NEXT:    [[STILL_POISON:%.*]] = and i32 [[POISON]], 0
; CGSCC-NEXT:    [[POISON_YET_AGAIN:%.*]] = getelementptr i32, i32* [[TMP0]], i32 [[STILL_POISON]]
; CGSCC-NEXT:    store i32 0, i32* [[POISON_YET_AGAIN]], align 4
; CGSCC-NEXT:    ret void
;
  %poison = sub nuw i32 0, 1           ; Results in a poison value.
  %still_poison = and i32 %poison, 0   ; 0, but also poison.
  %poison_yet_again = getelementptr i32, i32* %0, i32 %still_poison
  store i32 0, i32* %poison_yet_again  ; Undefined behavior due to store to poison.
  ret void
}

define void @inf_loop() #0 {
; TUNIT: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none)
; TUNIT-LABEL: define {{[^@]+}}@inf_loop
; TUNIT-SAME: () #[[ATTR8:[0-9]+]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    br label [[WHILE_BODY:%.*]]
; TUNIT:       while.body:
; TUNIT-NEXT:    br label [[WHILE_BODY]]
;
; CGSCC: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none)
; CGSCC-LABEL: define {{[^@]+}}@inf_loop
; CGSCC-SAME: () #[[ATTR10:[0-9]+]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    br label [[WHILE_BODY:%.*]]
; CGSCC:       while.body:
; CGSCC-NEXT:    br label [[WHILE_BODY]]
;
entry:
  br label %while.body

while.body:                                       ; preds = %entry, %while.body
  br label %while.body
}

; TEST 7: Infinite loop.
; FIXME: Detect infloops, and mark affected blocks dead.

define i32 @test5(i32, i32) #0 {
; CHECK: Function Attrs: nosync memory(none)
; CHECK-LABEL: define {{[^@]+}}@test5
; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR5:[0-9]+]] {
; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT:    br i1 [[TMP3]], label [[COND_IF:%.*]], label [[COND_ELSEIF:%.*]]
; CHECK:       cond.if:
; CHECK-NEXT:    [[TMP4:%.*]] = tail call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.elseif:
; CHECK-NEXT:    unreachable
; CHECK:       cond.else:
; CHECK-NEXT:    unreachable
; CHECK:       cond.end:
; CHECK-NEXT:    ret i32 0
;
  %3 = icmp sgt i32 %0, %1
  br i1 %3, label %cond.if, label %cond.elseif

cond.if:                                                ; preds = %2
  %4 = tail call i32 @bar()
  br label %cond.end

cond.elseif:                                                ; preds = %2
  call void @inf_loop()
  %5 = icmp slt i32 %0, %1
  br i1 %5, label %cond.end, label %cond.else

cond.else:                                                ; preds = %cond.elseif
  %6 = tail call i32 @foo()
  br label %cond.end

cond.end:                                               ; preds = %cond.if, %cond.else, %cond.elseif
  %7 = phi i32 [ %1, %cond.elseif ], [ 0, %cond.else ], [ 0, %cond.if ]
  ret i32 %7
}

define void @rec() #0 {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@rec
; TUNIT-SAME: () #[[ATTR9:[0-9]+]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@rec
; CGSCC-SAME: () #[[ATTR11:[0-9]+]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    ret void
;
entry:
  call void @rec()
  ret void
}

; TEST 8: Recursion
; FIXME: everything after first block should be marked dead
; and unreachable should be put after call to @rec().

define i32 @test6(i32, i32) #0 {
; CHECK-LABEL: define {{[^@]+}}@test6
; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT:    br i1 [[TMP3]], label [[COND_IF:%.*]], label [[COND_ELSEIF:%.*]]
; CHECK:       cond.if:
; CHECK-NEXT:    [[TMP4:%.*]] = tail call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.elseif:
; CHECK-NEXT:    [[TMP5:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT:    br i1 [[TMP5]], label [[COND_END]], label [[COND_ELSE:%.*]]
; CHECK:       cond.else:
; CHECK-NEXT:    [[TMP6:%.*]] = tail call i32 @foo()
; CHECK-NEXT:    br label [[COND_END]]
; CHECK:       cond.end:
; CHECK-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP1]], [[COND_ELSEIF]] ], [ 0, [[COND_ELSE]] ], [ 0, [[COND_IF]] ]
; CHECK-NEXT:    ret i32 [[TMP7]]
;
  call void @rec()
  %3 = icmp sgt i32 %0, %1
  br i1 %3, label %cond.if, label %cond.elseif

cond.if:                                                ; preds = %2
  %4 = tail call i32 @bar()
  br label %cond.end

cond.elseif:                                                ; preds = %2
  call void @rec()
  %5 = icmp slt i32 %0, %1
  br i1 %5, label %cond.end, label %cond.else

cond.else:                                                ; preds = %cond.elseif
  %6 = tail call i32 @foo()
  br label %cond.end

cond.end:                                               ; preds = %cond.if, %cond.else, %cond.elseif
  %7 = phi i32 [ %1, %cond.elseif ], [ 0, %cond.else ], [ 0, %cond.if ]
  ret i32 %7
}
; TEST 9: Recursion
; FIXME: contains recursive call to itself in cond.elseif block

define i32 @test7(i32, i32) #0 {
; CHECK-LABEL: define {{[^@]+}}@test7
; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
; CHECK-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT:    br i1 [[TMP3]], label [[COND_IF:%.*]], label [[COND_ELSEIF:%.*]]
; CHECK:       cond.if:
; CHECK-NEXT:    [[TMP4:%.*]] = tail call i32 @bar()
; CHECK-NEXT:    br label [[COND_END:%.*]]
; CHECK:       cond.elseif:
; CHECK-NEXT:    [[TMP5:%.*]] = tail call i32 @test7(i32 [[TMP0]], i32 [[TMP1]])
; CHECK-NEXT:    [[TMP6:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT:    br i1 [[TMP6]], label [[COND_END]], label [[COND_ELSE:%.*]]
; CHECK:       cond.else:
; CHECK-NEXT:    [[TMP7:%.*]] = tail call i32 @foo()
; CHECK-NEXT:    br label [[COND_END]]
; CHECK:       cond.end:
; CHECK-NEXT:    [[TMP8:%.*]] = phi i32 [ [[TMP1]], [[COND_ELSEIF]] ], [ 0, [[COND_ELSE]] ], [ 0, [[COND_IF]] ]
; CHECK-NEXT:    ret i32 [[TMP8]]
;
  %3 = icmp sgt i32 %0, %1
  br i1 %3, label %cond.if, label %cond.elseif

cond.if:                                                ; preds = %2
  %4 = tail call i32 @bar()
  br label %cond.end

cond.elseif:                                                ; preds = %2
  %5 = tail call i32 @test7(i32 %0, i32 %1)
  %6 = icmp slt i32 %0, %1
  br i1 %6, label %cond.end, label %cond.else

cond.else:                                                ; preds = %cond.elseif
  %7 = tail call i32 @foo()
  br label %cond.end

cond.end:                                               ; preds = %cond.if, %cond.else, %cond.elseif
  %8 = phi i32 [ %1, %cond.elseif ], [ 0, %cond.else ], [ 0, %cond.if ]
  ret i32 %8
}

; SCC test
;
; char a1 __attribute__((aligned(8)));
; char a2 __attribute__((aligned(16)));
;
; char* f1(char* a ){
;     return a?a:f2(&a1);
; }
; char* f2(char* a){
;     return a?f1(a):f3(&a2);
; }
;
; char* f3(char* a){
;     return a?&a1: f1(&a2);
; }

@a1 = common global i8 0, align 8
@a2 = common global i8 0, align 16

define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 {
; CGSCC-LABEL: define {{[^@]+}}@f1
; CGSCC-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
; CGSCC:       3:
; CGSCC-NEXT:    [[TMP4:%.*]] = tail call i8* @f2(i8* nonnull @a1)
; CGSCC-NEXT:    br label [[TMP5]]
; CGSCC:       5:
; CGSCC-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]
; CGSCC-NEXT:    ret i8* [[TMP6]]
;
  %2 = icmp eq i8* %0, null
  br i1 %2, label %3, label %5

; <label>:3:                                      ; preds = %1
  %4 = tail call i8* @f2(i8* nonnull @a1)
  br label %5

; <label>:5:                                      ; preds = %1, %3
  %6 = phi i8* [ %4, %3 ], [ %0, %1 ]
  ret i8* %6
}

define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 {
; CGSCC-LABEL: define {{[^@]+}}@f2
; CGSCC-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
; CGSCC:       3:
; CGSCC-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull [[TMP0]])
; CGSCC-NEXT:    br label [[TMP7:%.*]]
; CGSCC:       5:
; CGSCC-NEXT:    [[TMP6:%.*]] = tail call i8* @f3(i8* nonnull @a2)
; CGSCC-NEXT:    br label [[TMP7]]
; CGSCC:       7:
; CGSCC-NEXT:    [[TMP8:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP6]], [[TMP5]] ]
; CGSCC-NEXT:    ret i8* [[TMP8]]
;
  %2 = icmp eq i8* %0, null
  br i1 %2, label %5, label %3

; <label>:3:                                      ; preds = %1

  %4 = tail call i8* @f1(i8* nonnull %0)
  br label %7

; <label>:5:                                      ; preds = %1
  %6 = tail call i8* @f3(i8* nonnull @a2)
  br label %7

; <label>:7:                                      ; preds = %5, %3
  %8 = phi i8* [ %4, %3 ], [ %6, %5 ]
  ret i8* %8
}

define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 {
; CGSCC-LABEL: define {{[^@]+}}@f3
; CGSCC-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr {
; CGSCC-NEXT:    [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null
; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]
; CGSCC:       3:
; CGSCC-NEXT:    [[TMP4:%.*]] = tail call i8* @f1(i8* nonnull @a2)
; CGSCC-NEXT:    br label [[TMP5]]
; CGSCC:       5:
; CGSCC-NEXT:    [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ @a1, [[TMP1:%.*]] ]
; CGSCC-NEXT:    ret i8* [[TMP6]]
;
  %2 = icmp eq i8* %0, null
  br i1 %2, label %3, label %5

; <label>:3:                                      ; preds = %1
  %4 = tail call i8* @f1(i8* nonnull @a2)
  br label %5

; <label>:5:                                      ; preds = %1, %3
  %6 = phi i8* [ %4, %3 ], [ @a1, %1 ]
  ret i8* %6
}

declare void @sink() nofree nosync nounwind willreturn
define void @test_unreachable() {
; TUNIT: Function Attrs: nofree noreturn nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@test_unreachable
; TUNIT-SAME: () #[[ATTR0]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13:[0-9]+]]
; TUNIT-NEXT:    call void @test_unreachable() #[[ATTR0]]
; TUNIT-NEXT:    unreachable
;
; CGSCC: Function Attrs: nofree noreturn nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@test_unreachable
; CGSCC-SAME: () #[[ATTR0]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15:[0-9]+]]
; CGSCC-NEXT:    call void @test_unreachable() #[[ATTR0]]
; CGSCC-NEXT:    unreachable
;
  call void @sink()
  call void @test_unreachable()
  unreachable
}

define linkonce_odr void @non_exact1() {
; CHECK-LABEL: define {{[^@]+}}@non_exact1() {
; CHECK-NEXT:    call void @non_dead_a0() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a1() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a2() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a3() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a4() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a5() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a6() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a7() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a8() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a9() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a10() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a11() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a12() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a13() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a14() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_a15() #[[ATTR2]]
; CHECK-NEXT:    call void @middle()
; CHECK-NEXT:    ret void
;
  call void @non_dead_a0()
  call void @non_dead_a1()
  call void @non_dead_a2()
  call void @non_dead_a3()
  call void @non_dead_a4()
  call void @non_dead_a5()
  call void @non_dead_a6()
  call void @non_dead_a7()
  call void @non_dead_a8()
  call void @non_dead_a9()
  call void @non_dead_a10()
  call void @non_dead_a11()
  call void @non_dead_a12()
  call void @non_dead_a13()
  call void @non_dead_a14()
  call void @non_dead_a15()
  call void @middle()
  ret void
}
define internal void @middle() {
; TUNIT-LABEL: define {{[^@]+}}@middle() {
; TUNIT-NEXT:  bb0:
; TUNIT-NEXT:    call void @non_dead_b0() #[[ATTR10:[0-9]+]]
; TUNIT-NEXT:    call void @non_dead_b1() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b2() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b3() #[[ATTR10]]
; TUNIT-NEXT:    br label [[BB1:%.*]]
; TUNIT:       bb1:
; TUNIT-NEXT:    call void @non_dead_b4() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b5() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b6() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b7() #[[ATTR10]]
; TUNIT-NEXT:    br label [[BB2:%.*]]
; TUNIT:       bb2:
; TUNIT-NEXT:    call void @non_dead_b8() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b9() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b10() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b11() #[[ATTR10]]
; TUNIT-NEXT:    br label [[BB3:%.*]]
; TUNIT:       bb3:
; TUNIT-NEXT:    call void @non_dead_b12() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b13() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b14() #[[ATTR10]]
; TUNIT-NEXT:    call void @non_dead_b15() #[[ATTR10]]
; TUNIT-NEXT:    br label [[BB4:%.*]]
; TUNIT:       bb4:
; TUNIT-NEXT:    call void @non_exact2()
; TUNIT-NEXT:    ret void
;
; CGSCC-LABEL: define {{[^@]+}}@middle() {
; CGSCC-NEXT:  bb0:
; CGSCC-NEXT:    call void @non_dead_b0() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b1() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b2() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b3() #[[ATTR15]]
; CGSCC-NEXT:    br label [[BB1:%.*]]
; CGSCC:       bb1:
; CGSCC-NEXT:    call void @non_dead_b4() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b5() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b6() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b7() #[[ATTR15]]
; CGSCC-NEXT:    br label [[BB2:%.*]]
; CGSCC:       bb2:
; CGSCC-NEXT:    call void @non_dead_b8() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b9() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b10() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b11() #[[ATTR15]]
; CGSCC-NEXT:    br label [[BB3:%.*]]
; CGSCC:       bb3:
; CGSCC-NEXT:    call void @non_dead_b12() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b13() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b14() #[[ATTR15]]
; CGSCC-NEXT:    call void @non_dead_b15() #[[ATTR15]]
; CGSCC-NEXT:    br label [[BB4:%.*]]
; CGSCC:       bb4:
; CGSCC-NEXT:    call void @non_exact2()
; CGSCC-NEXT:    ret void
;
bb0:
  call void @non_dead_b0()
  call void @non_dead_b1()
  call void @non_dead_b2()
  call void @non_dead_b3()
br label %bb1
bb1:
  call void @non_dead_b4()
  call void @non_dead_b5()
  call void @non_dead_b6()
  call void @non_dead_b7()
br label %bb2
bb2:
  call void @non_dead_b8()
  call void @non_dead_b9()
  call void @non_dead_b10()
  call void @non_dead_b11()
br label %bb3
bb3:
  call void @non_dead_b12()
  call void @non_dead_b13()
  call void @non_dead_b14()
  call void @non_dead_b15()
br label %bb4
bb4:
  call void @non_exact2()
  ret void
}
define linkonce_odr void @non_exact2() {
; CHECK-LABEL: define {{[^@]+}}@non_exact2() {
; CHECK-NEXT:    call void @non_dead_c0() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c1() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c2() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c3() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c4() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c5() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c6() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c7() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c8() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c9() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c10() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c11() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c12() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c13() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c14() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_c15() #[[ATTR2]]
; CHECK-NEXT:    call void @non_exact3()
; CHECK-NEXT:    ret void
;
  call void @non_dead_c0()
  call void @non_dead_c1()
  call void @non_dead_c2()
  call void @non_dead_c3()
  call void @non_dead_c4()
  call void @non_dead_c5()
  call void @non_dead_c6()
  call void @non_dead_c7()
  call void @non_dead_c8()
  call void @non_dead_c9()
  call void @non_dead_c10()
  call void @non_dead_c11()
  call void @non_dead_c12()
  call void @non_dead_c13()
  call void @non_dead_c14()
  call void @non_dead_c15()
  call void @non_exact3()
  ret void
}
define linkonce_odr void @non_exact3() {
; CHECK-LABEL: define {{[^@]+}}@non_exact3() {
; CHECK-NEXT:    call void @non_dead_d0() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d1() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d2() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d3() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d4() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d5() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d6() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d7() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d8() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d9() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d10() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d11() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d12() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d13() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d14() #[[ATTR2]]
; CHECK-NEXT:    call void @non_dead_d15() #[[ATTR2]]
; CHECK-NEXT:    [[NR:%.*]] = call i32 @foo_noreturn() #[[ATTR4]]
; CHECK-NEXT:    unreachable
;
  call void @non_dead_d0()
  call void @non_dead_d1()
  call void @non_dead_d2()
  call void @non_dead_d3()
  call void @non_dead_d4()
  call void @non_dead_d5()
  call void @non_dead_d6()
  call void @non_dead_d7()
  call void @non_dead_d8()
  call void @non_dead_d9()
  call void @non_dead_d10()
  call void @non_dead_d11()
  call void @non_dead_d12()
  call void @non_dead_d13()
  call void @non_dead_d14()
  call void @non_dead_d15()
  %nr = call i32 @foo_noreturn()
  call void @dead_e1()
  ret void
}

define internal void @non_dead_a0() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a0
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a0
; CGSCC-SAME: () #[[ATTR12:[0-9]+]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a1() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a1
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a1
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a2() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a2
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a2
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a3() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a3
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a3
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a4() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a4
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a4
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a5() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a5
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a5
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a6() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a6
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a6
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a7() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a7
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a7
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a8() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a8
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a8
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a9() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a9
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a9
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a10() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a10
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a10
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a11() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a11
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a11
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a12() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a12
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a12
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a13() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a13
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a13
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a14() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a14
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a14
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_a15() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_a15
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_a15
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b0() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b0
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b0
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b1() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b1
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b1
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b2() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b2
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b2
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b3() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b3
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b3
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b4() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b4
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b4
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b5() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b5
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b5
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b6() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b6
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b6
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b7() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b7
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b7
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b8() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b8
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b8
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b9() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b9
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b9
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b10() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b10
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b10
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b11() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b11
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b11
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b12() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b12
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b12
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b13() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b13
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b13
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b14() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b14
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b14
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_b15() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_b15
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_b15
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c0() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c0
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c0
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c1() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c1
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c1
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c2() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c2
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c2
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c3() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c3
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c3
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c4() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c4
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c4
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c5() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c5
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c5
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c6() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c6
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c6
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c7() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c7
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c7
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c8() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c8
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c8
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c9() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c9
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c9
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c10() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c10
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c10
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c11() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c11
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c11
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c12() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c12
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c12
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c13() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c13
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c13
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c14() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c14
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c14
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_c15() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_c15
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_c15
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d0() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d0
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d0
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d1() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d1
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d1
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d2() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d2
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d2
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d3() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d3
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d3
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d4() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d4
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d4
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d5() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d5
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d5
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d6() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d6
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d6
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d7() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d7
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d7
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d8() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d8
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d8
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d9() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d9
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d9
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d10() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d10
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d10
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d11() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d11
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d11
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d12() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d12
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d12
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d13() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d13
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d13
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d14() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d14
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d14
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @non_dead_d15() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@non_dead_d15
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@non_dead_d15
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}
define internal void @dead_e0() { call void @dead_e1() ret void }
; CGSCC-LABEL: define {{[^@]+}}@dead_e0() {
; CGSCC-NEXT:    call void @dead_e1()
; CGSCC-NEXT:    ret void
;
define internal void @dead_e1() { call void @dead_e2() ret void }
define internal void @dead_e2() { ret void }

; Verify we actually deduce information for these functions.

declare void @blowup() noreturn
define void @live_with_dead_entry() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
  invoke void @blowup() to label %live_with_dead_entry unwind label %lpad
lpad:
  %0 = landingpad { i8*, i32 } catch i8* null
  br label %live_with_dead_entry
live_with_dead_entry:
  ret void
}

define void @live_with_dead_entry_lp() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK: Function Attrs: nounwind
; CHECK-LABEL: define {{[^@]+}}@live_with_dead_entry_lp
; CHECK-SAME: () #[[ATTR2]] personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    invoke void @blowup() #[[ATTR4]]
; CHECK-NEXT:    to label [[LIVE_WITH_DEAD_ENTRY_DEAD:%.*]] unwind label [[LP1:%.*]]
; CHECK:       lp1:
; CHECK-NEXT:    [[LP:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT:    catch i8* null
; CHECK-NEXT:    invoke void @blowup() #[[ATTR4]]
; CHECK-NEXT:    to label [[LIVE_WITH_DEAD_ENTRY_DEAD1:%.*]] unwind label [[LP2:%.*]]
; CHECK:       lp2:
; CHECK-NEXT:    [[TMP0:%.*]] = landingpad { i8*, i32 }
; CHECK-NEXT:    catch i8* null
; CHECK-NEXT:    br label [[LIVE_WITH_DEAD_ENTRY:%.*]]
; CHECK:       live_with_dead_entry.dead:
; CHECK-NEXT:    unreachable
; CHECK:       live_with_dead_entry.dead1:
; CHECK-NEXT:    unreachable
; CHECK:       live_with_dead_entry:
; CHECK-NEXT:    ret void
;
entry:
  invoke void @blowup() to label %live_with_dead_entry unwind label %lp1
lp1:
  %lp = landingpad { i8*, i32 } catch i8* null
  invoke void @blowup() to label %live_with_dead_entry unwind label %lp2
lp2:
  %0 = landingpad { i8*, i32 } catch i8* null
  br label %live_with_dead_entry
live_with_dead_entry:
  ret void
}

define internal void @useless_arg_sink(i32* %a) {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@useless_arg_sink
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@useless_arg_sink
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @sink()
  ret void
}

define internal void @useless_arg_almost_sink(i32* %a) {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@useless_arg_almost_sink
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    call void @useless_arg_sink() #[[ATTR10]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@useless_arg_almost_sink
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    call void @useless_arg_sink() #[[ATTR15]]
; CGSCC-NEXT:    ret void
;
  call void @useless_arg_sink(i32* %a)
  ret void
}

; Check we do not annotate the function interface of this weak function.
define weak_odr void @useless_arg_ext(i32* %a) {
; CHECK-LABEL: define {{[^@]+}}@useless_arg_ext
; CHECK-SAME: (i32* [[A:%.*]]) {
; CHECK-NEXT:    call void @useless_arg_almost_sink() #[[ATTR2]]
; CHECK-NEXT:    ret void
;
  call void @useless_arg_almost_sink(i32* %a)
  ret void
}

define internal void @useless_arg_ext_int(i32* %a) {
; CHECK-LABEL: define {{[^@]+}}@useless_arg_ext_int
; CHECK-SAME: (i32* [[A:%.*]]) {
; CHECK-NEXT:    call void @useless_arg_ext(i32* [[A]])
; CHECK-NEXT:    ret void
;
  call void @useless_arg_ext(i32* %a)
  ret void
}

define void @useless_arg_ext_int_ext(i32* %a) {
; CHECK-LABEL: define {{[^@]+}}@useless_arg_ext_int_ext
; CHECK-SAME: (i32* [[A:%.*]]) {
; CHECK-NEXT:    call void @useless_arg_ext_int(i32* [[A]])
; CHECK-NEXT:    ret void
;
  call void @useless_arg_ext_int(i32* %a)
  ret void
}

; FIXME: We should fold terminators.

define internal i32 @switch_default(i64 %i) nounwind {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@switch_default
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    switch i64 0, label [[SW_DEFAULT:%.*]] [
; TUNIT-NEXT:    i64 3, label [[RETURN:%.*]]
; TUNIT-NEXT:    i64 10, label [[RETURN]]
; TUNIT-NEXT:    ]
; TUNIT:       sw.default:
; TUNIT-NEXT:    call void @sink() #[[ATTR13]]
; TUNIT-NEXT:    ret i32 undef
; TUNIT:       return:
; TUNIT-NEXT:    unreachable
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@switch_default
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    switch i64 0, label [[SW_DEFAULT:%.*]] [
; CGSCC-NEXT:    i64 3, label [[RETURN:%.*]]
; CGSCC-NEXT:    i64 10, label [[RETURN]]
; CGSCC-NEXT:    ]
; CGSCC:       sw.default:
; CGSCC-NEXT:    call void @sink() #[[ATTR15]]
; CGSCC-NEXT:    ret i32 123
; CGSCC:       return:
; CGSCC-NEXT:    unreachable
;
entry:
  switch i64 %i, label %sw.default [
  i64 3, label %return
  i64 10, label %return
  ]

sw.default:
  call void @sink()
  ret i32 123

return:
  ret i32 0
}

define i32 @switch_default_caller() {
; TUNIT: Function Attrs: nofree nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@switch_default_caller
; TUNIT-SAME: () #[[ATTR10]] {
; TUNIT-NEXT:    [[CALL2:%.*]] = tail call i32 @switch_default() #[[ATTR10]]
; TUNIT-NEXT:    ret i32 123
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@switch_default_caller
; CGSCC-SAME: () #[[ATTR12]] {
; CGSCC-NEXT:    [[CALL2:%.*]] = tail call noundef i32 @switch_default() #[[ATTR15]]
; CGSCC-NEXT:    ret i32 [[CALL2]]
;
  %call2 = tail call i32 @switch_default(i64 0)
  ret i32 %call2
}

define internal i32 @switch_default_dead(i64 %i) nounwind {
; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@switch_default_dead
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    switch i64 0, label [[SW_DEFAULT:%.*]] [
; CGSCC-NEXT:    i64 3, label [[RETURN:%.*]]
; CGSCC-NEXT:    i64 10, label [[RETURN]]
; CGSCC-NEXT:    ]
; CGSCC:       sw.default:
; CGSCC-NEXT:    ret i32 123
; CGSCC:       return:
; CGSCC-NEXT:    unreachable
;
entry:
  switch i64 %i, label %sw.default [
  i64 3, label %return
  i64 10, label %return
  ]

sw.default:
  ret i32 123

return:
  ret i32 0
}

define i32 @switch_default_dead_caller() {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@switch_default_dead_caller
; TUNIT-SAME: () #[[ATTR11:[0-9]+]] {
; TUNIT-NEXT:    ret i32 123
;
; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@switch_default_dead_caller
; CGSCC-SAME: () #[[ATTR11]] {
; CGSCC-NEXT:    [[CALL2:%.*]] = tail call noundef i32 @switch_default_dead() #[[ATTR16:[0-9]+]]
; CGSCC-NEXT:    ret i32 [[CALL2]]
;
  %call2 = tail call i32 @switch_default_dead(i64 0)
  ret i32 %call2
}

define void @call_via_pointer_with_dead_args(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args
; CHECK-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull [[FP:%.*]]) {
; CHECK-NEXT:    call void [[FP]](i32* [[A]], i32* [[B]], i32* [[A]], i64 -1, i32** null)
; CHECK-NEXT:    ret void
;
  call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
  ret void
}

define internal void @call_via_pointer_with_dead_args_internal_a(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
; CHECK-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
; CHECK-NEXT:    call void @called_via_pointer(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; CHECK-NEXT:    ret void
;
  call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
  ret void
}
define internal void @call_via_pointer_with_dead_args_internal_b(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; TUNIT-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
; TUNIT-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
; TUNIT-NEXT:    call void @called_via_pointer_internal_2(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; TUNIT-NEXT:    ret void
;
; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
; CGSCC-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
; CGSCC-NEXT:    call void @called_via_pointer_internal_2(i32* [[A]])
; CGSCC-NEXT:    ret void
;
  call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
  ret void
}
define void @call_via_pointer_with_dead_args_caller(i32* %a, i32* %b) {
; TUNIT-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
; TUNIT-SAME: (i32* [[A:%.*]], i32* [[B:%.*]]) {
; TUNIT-NEXT:    [[PTR1:%.*]] = alloca i32, align 128
; TUNIT-NEXT:    [[PTR2:%.*]] = alloca i32, align 128
; TUNIT-NEXT:    [[PTR3:%.*]] = alloca i32, align 128
; TUNIT-NEXT:    [[PTR4:%.*]] = alloca i32, align 128
; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef @called_via_pointer)
; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef @called_via_pointer_internal_1)
; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR3]])
; TUNIT-NEXT:    call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR4]])
; TUNIT-NEXT:    ret void
;
; CGSCC-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_caller
; CGSCC-SAME: (i32* [[A:%.*]], i32* [[B:%.*]]) {
; CGSCC-NEXT:    [[PTR1:%.*]] = alloca i32, align 128
; CGSCC-NEXT:    [[PTR2:%.*]] = alloca i32, align 128
; CGSCC-NEXT:    [[PTR3:%.*]] = alloca i32, align 128
; CGSCC-NEXT:    [[PTR4:%.*]] = alloca i32, align 128
; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer)
; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer_internal_1)
; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR3]])
; CGSCC-NEXT:    call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR4]])
; CGSCC-NEXT:    ret void
;
  %ptr1 = alloca i32, align 128
  %ptr2 = alloca i32, align 128
  %ptr3 = alloca i32, align 128
  %ptr4 = alloca i32, align 128
  call void @call_via_pointer_with_dead_args(i32* %a, i32* %ptr1, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer)
  call void @call_via_pointer_with_dead_args(i32* %a, i32* %ptr2, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer_internal_1)
  call void @call_via_pointer_with_dead_args_internal_a(i32* %b, i32* %ptr3, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer)
  call void @call_via_pointer_with_dead_args_internal_b(i32* %b, i32* %ptr4, void (i32*, i32*, i32*, i64, i32**)* @called_via_pointer_internal_2)
  ret void
}
define void @called_via_pointer(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
; CHECK-LABEL: define {{[^@]+}}@called_via_pointer
; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT:    tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT:    ret void
;
entry:
  tail call void @use_i32p(i32* %a)
  tail call void @use_i32p(i32* %a)
  ret void
}
define internal void @called_via_pointer_internal_1(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
; CHECK-LABEL: define {{[^@]+}}@called_via_pointer_internal_1
; CHECK-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT:    tail call void @use_i32p(i32* [[A]])
; CHECK-NEXT:    ret void
;
entry:
  tail call void @use_i32p(i32* %a)
  tail call void @use_i32p(i32* %a)
  ret void
}
; FIXME: Figure out why the MODULE has the unused arguments still
define internal void @called_via_pointer_internal_2(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
; TUNIT-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
; TUNIT-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    tail call void @use_i32p(i32* [[A]])
; TUNIT-NEXT:    tail call void @use_i32p(i32* [[A]])
; TUNIT-NEXT:    ret void
;
; CGSCC-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
; CGSCC-SAME: (i32* [[A:%.*]]) {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    tail call void @use_i32p(i32* [[A]])
; CGSCC-NEXT:    tail call void @use_i32p(i32* [[A]])
; CGSCC-NEXT:    ret void
;
entry:
  tail call void @use_i32p(i32* %a)
  tail call void @use_i32p(i32* %a)
  ret void
}
declare void @use_i32p(i32*)

; Allow blockaddress users
define internal void @dead_with_blockaddress_users(i32* nocapture %pc) nounwind readonly {
; CGSCC: Function Attrs: nounwind memory(read)
; CGSCC-LABEL: define {{[^@]+}}@dead_with_blockaddress_users
; CGSCC-SAME: (i32* nocapture [[PC:%.*]]) #[[ATTR13:[0-9]+]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    br label [[INDIRECTGOTO:%.*]]
; CGSCC:       lab0:
; CGSCC-NEXT:    [[INDVAR_NEXT:%.*]] = add i32 [[INDVAR:%.*]], 1
; CGSCC-NEXT:    br label [[INDIRECTGOTO]]
; CGSCC:       end:
; CGSCC-NEXT:    ret void
; CGSCC:       indirectgoto:
; CGSCC-NEXT:    [[INDVAR]] = phi i32 [ [[INDVAR_NEXT]], [[LAB0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CGSCC-NEXT:    [[PC_ADDR_0:%.*]] = getelementptr i32, i32* [[PC]], i32 [[INDVAR]]
; CGSCC-NEXT:    [[TMP1_PN:%.*]] = load i32, i32* [[PC_ADDR_0]], align 4
; CGSCC-NEXT:    [[INDIRECT_GOTO_DEST_IN:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @dead_with_blockaddress_users.l, i32 0, i32 [[TMP1_PN]]
; CGSCC-NEXT:    [[INDIRECT_GOTO_DEST:%.*]] = load i8*, i8** [[INDIRECT_GOTO_DEST_IN]], align 8
; CGSCC-NEXT:    indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end]
;
entry:
  br label %indirectgoto

lab0:                                             ; preds = %indirectgoto
  %indvar.next = add i32 %indvar, 1               ; <i32> [#uses=1]
  br label %indirectgoto

end:                                              ; preds = %indirectgoto
  ret void

indirectgoto:                                     ; preds = %lab0, %entry
  %indvar = phi i32 [ %indvar.next, %lab0 ], [ 0, %entry ] ; <i32> [#uses=2]
  %pc.addr.0 = getelementptr i32, i32* %pc, i32 %indvar ; <i32*> [#uses=1]
  %tmp1.pn = load i32, i32* %pc.addr.0                 ; <i32> [#uses=1]
  %indirect.goto.dest.in = getelementptr inbounds [2 x i8*], [2 x i8*]* @dead_with_blockaddress_users.l, i32 0, i32 %tmp1.pn ; <i8**> [#uses=1]
  %indirect.goto.dest = load i8*, i8** %indirect.goto.dest.in ; <i8*> [#uses=1]
  indirectbr i8* %indirect.goto.dest, [label %lab0, label %end]
}


; The code below exposed a bug that caused %call to be replaced with `undef`.

%struct.a = type { %struct.a* }

@e = global %struct.a* null

define i32 @main() {
; CHECK-LABEL: define {{[^@]+}}@main() {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[F:%.*]] = alloca i32, align 4
; CHECK-NEXT:    br label [[FOR_COND_0:%.*]]
; CHECK:       for.cond.0:
; CHECK-NEXT:    [[G_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_0:%.*]] ]
; CHECK-NEXT:    [[CMP_0:%.*]] = icmp ult i32 [[G_0]], 100
; CHECK-NEXT:    br i1 [[CMP_0]], label [[FOR_BODY_0]], label [[FOR_END_0:%.*]]
; CHECK:       for.body.0:
; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[G_0]], 1
; CHECK-NEXT:    br label [[FOR_COND_0]]
; CHECK:       for.end.0:
; CHECK-NEXT:    [[CALL:%.*]] = call i8* @malloc(i64 noundef 8)
; CHECK-NEXT:    store i8* [[CALL]], i8** bitcast (%struct.a** @e to i8**), align 8
; CHECK-NEXT:    [[B:%.*]] = bitcast i8* [[CALL]] to %struct.a**
; CHECK-NEXT:    store %struct.a* null, %struct.a** [[B]], align 8
; CHECK-NEXT:    br label [[FOR_COND_1:%.*]]
; CHECK:       for.cond.1:
; CHECK-NEXT:    [[G_1:%.*]] = phi i32 [ 0, [[FOR_END_0]] ], [ [[INC6:%.*]], [[FOR_BODY_1:%.*]] ]
; CHECK-NEXT:    [[CMP_1:%.*]] = icmp ult i32 [[G_1]], 100
; CHECK-NEXT:    br i1 [[CMP_1]], label [[FOR_BODY_1]], label [[FOR_END_1:%.*]]
; CHECK:       for.body.1:
; CHECK-NEXT:    [[CALL4:%.*]] = call i32 (i32*, ...) bitcast (i32 (i32)* @h to i32 (i32*, ...)*)(i32* nonnull [[F]])
; CHECK-NEXT:    [[INC6]] = add nuw nsw i32 [[G_1]], 1
; CHECK-NEXT:    br label [[FOR_COND_1]]
; CHECK:       for.end.1:
; CHECK-NEXT:    ret i32 0
;
entry:
  %f = alloca i32
  br label %for.cond.0

for.cond.0:
  %g.0 = phi i32 [ 0, %entry ], [ %inc, %for.body.0 ]
  %cmp.0 = icmp ult i32 %g.0, 100
  br i1 %cmp.0, label %for.body.0, label %for.end.0

for.body.0:
  %inc = add nuw nsw i32 %g.0, 1
  br label %for.cond.0

for.end.0:
  %call = call i8* @malloc(i64 8)
  store i8* %call, i8** bitcast (%struct.a** @e to i8**)
  %b = bitcast i8* %call to %struct.a**
  store %struct.a* null, %struct.a** %b
  br label %for.cond.1

for.cond.1:
  %g.1 = phi i32 [ 0, %for.end.0 ], [ %inc6, %for.body.1 ]
  %cmp.1 = icmp ult i32 %g.1, 100
  br i1 %cmp.1, label %for.body.1, label %for.end.1

for.body.1:
  %call4 = call i32 (i32*, ...) bitcast (i32 (i32)* @h to i32 (i32*, ...)*)(i32* nonnull %f)
  %inc6 = add nuw nsw i32 %g.1, 1
  br label %for.cond.1

for.end.1:
  ret i32 0
}

declare noalias i8* @malloc(i64)

define i32 @h(i32 %i) {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@h
; TUNIT-SAME: (i32 [[I:%.*]]) #[[ATTR11]] {
; TUNIT-NEXT:    ret i32 0
;
; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@h
; CGSCC-SAME: (i32 [[I:%.*]]) #[[ATTR6]] {
; CGSCC-NEXT:    ret i32 0
;
  ret i32 0
}


; Verify we do not choke on the GEP in the unreachable block.

@p = global i8 0

define void @bad_gep() {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@bad_gep
; TUNIT-SAME: () #[[ATTR11]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    [[N:%.*]] = alloca i8, align 1
; TUNIT-NEXT:    [[M:%.*]] = alloca i8, align 1
; TUNIT-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR14:[0-9]+]]
; TUNIT-NEXT:    br label [[EXIT:%.*]]
; TUNIT:       while.body:
; TUNIT-NEXT:    unreachable
; TUNIT:       if.then:
; TUNIT-NEXT:    unreachable
; TUNIT:       if.end:
; TUNIT-NEXT:    unreachable
; TUNIT:       exit:
; TUNIT-NEXT:    call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR14]]
; TUNIT-NEXT:    ret void
;
; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@bad_gep
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[N:%.*]] = alloca i8, align 1
; CGSCC-NEXT:    [[M:%.*]] = alloca i8, align 1
; CGSCC-NEXT:    call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR16]]
; CGSCC-NEXT:    br label [[EXIT:%.*]]
; CGSCC:       while.body:
; CGSCC-NEXT:    unreachable
; CGSCC:       if.then:
; CGSCC-NEXT:    unreachable
; CGSCC:       if.end:
; CGSCC-NEXT:    unreachable
; CGSCC:       exit:
; CGSCC-NEXT:    call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR16]]
; CGSCC-NEXT:    ret void
;
entry:
  %n = alloca i8
  %m = alloca i8
  call void @llvm.lifetime.start.p0i8(i64 1, i8* %n)
  br label %exit

while.body:
  %call = call i1 @bad_gep_helper1(i8* %n, i8* %ptr, i8* %m)
  br i1 %call, label %if.then, label %if.end

if.then:
  %0 = load i8, i8* %ptr
  call void @bad_gep_helper2(i8 %0)
  br label %if.end

if.end:
  %ptr = getelementptr inbounds i8, i8* %ptr, i64 1
  %cmp = icmp eq i8* %ptr, @p
  br i1 %cmp, label %exit, label %while.body

exit:
  call void @llvm.lifetime.end.p0i8(i64 1, i8* %n)
  ret void
}

define i8 @edge_vs_block_liveness() {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@edge_vs_block_liveness
; TUNIT-SAME: () #[[ATTR11]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    br i1 true, label [[B1:%.*]], label [[B2:%.*]]
; TUNIT:       b1:
; TUNIT-NEXT:    br label [[B2]]
; TUNIT:       b2:
; TUNIT-NEXT:    [[PHI:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ 1, [[B1]] ]
; TUNIT-NEXT:    ret i8 1
;
; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@edge_vs_block_liveness
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    br i1 true, label [[B1:%.*]], label [[B2:%.*]]
; CGSCC:       b1:
; CGSCC-NEXT:    br label [[B2]]
; CGSCC:       b2:
; CGSCC-NEXT:    [[PHI:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ 1, [[B1]] ]
; CGSCC-NEXT:    ret i8 1
;
entry:
  br i1 true, label %b1, label %b2
b1:
  br label %b2
b2:
  %phi = phi i8 [0, %entry], [1, %b1]
  ret i8 %phi
}

declare i1 @bad_gep_helper1(i8*, i8*, i8*)
declare void @bad_gep_helper2(i8)

declare void @llvm.lifetime.start.p0i8(i64 %0, i8* %1)
declare void @llvm.lifetime.end.p0i8(i64 %0, i8* %1)
;.
; TUNIT: attributes #[[ATTR0]] = { nofree noreturn nosync nounwind }
; TUNIT: attributes #[[ATTR1:[0-9]+]] = { memory(none) }
; TUNIT: attributes #[[ATTR2]] = { nounwind }
; TUNIT: attributes #[[ATTR3]] = { noreturn nounwind }
; TUNIT: attributes #[[ATTR4]] = { noreturn }
; TUNIT: attributes #[[ATTR5]] = { nosync memory(none) }
; TUNIT: attributes #[[ATTR6]] = { nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable }
; TUNIT: attributes #[[ATTR7]] = { nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR8]] = { nofree norecurse noreturn nosync nounwind memory(none) }
; TUNIT: attributes #[[ATTR9]] = { nofree nosync nounwind willreturn memory(none) }
; TUNIT: attributes #[[ATTR10]] = { nofree nosync nounwind willreturn }
; TUNIT: attributes #[[ATTR11]] = { nofree norecurse nosync nounwind willreturn memory(none) }
; TUNIT: attributes #[[ATTR12:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR13]] = { nounwind willreturn }
; TUNIT: attributes #[[ATTR14]] = { willreturn }
;.
; CGSCC: attributes #[[ATTR0]] = { nofree noreturn nosync nounwind }
; CGSCC: attributes #[[ATTR1:[0-9]+]] = { memory(none) }
; CGSCC: attributes #[[ATTR2]] = { nounwind }
; CGSCC: attributes #[[ATTR3]] = { noreturn nounwind }
; CGSCC: attributes #[[ATTR4]] = { noreturn }
; CGSCC: attributes #[[ATTR5]] = { nosync memory(none) }
; CGSCC: attributes #[[ATTR6]] = { nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR7]] = { nofree norecurse nounwind willreturn memory(argmem: readwrite) uwtable }
; CGSCC: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn memory(none) uwtable }
; CGSCC: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; CGSCC: attributes #[[ATTR10]] = { nofree norecurse noreturn nosync nounwind memory(none) }
; CGSCC: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR12]] = { nofree nosync nounwind willreturn }
; CGSCC: attributes #[[ATTR13]] = { nounwind memory(read) }
; CGSCC: attributes #[[ATTR14:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR15]] = { nounwind willreturn }
; CGSCC: attributes #[[ATTR16]] = { willreturn }
;.
